package com.mymarkdown.app.websocket.handler;

import cn.hutool.core.io.IoUtil;
import com.mymarkdown.app.common.ChainHandlerResult;
import com.mymarkdown.app.common.constant.Constant;
import com.mymarkdown.app.interfaces.ModifyWindow;
import com.mymarkdown.app.interfaces.RemotePullMdService;
import com.mymarkdown.app.interfaces.UserInfoService;
import com.mymarkdown.app.service.SaveMdBodyService;
import com.mymarkdown.app.util.ThreadPool;
import com.mymarkdown.app.websocket.enums.MessageTypeEnum;
import com.mymarkdown.app.websocket.interfaces.HandlerMessage;
import com.mymarkdown.app.websocket.interfaces.WebSocketSendMessage;
import com.mymarkdown.app.websocket.message.MessagePojo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.websocket.Session;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;

/**
 * @author zenglun
 * @date 2021/12/5 12:08 下午
 * @description: 保存md文件内容
 */
@Slf4j
@Component
public class SaveMdBodyHandlerMessageImpl implements HandlerMessage, SaveMdBodyService {

    @Autowired
    private CacheManager cacheManager;

    private Cache cache;

    @Autowired
    private RemotePullMdService remotePullMdService;

    @Autowired
    private WebSocketSendMessage webSocketSendMessage;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private ModifyWindow modifyWindow;


    @PostConstruct
    public void init() {
        cache = cacheManager.getCache(Constant.AllCacheKey.SAVE_MD_BODY_CACHE);
    }


    @Override
    public ChainHandlerResult onMessage(String message, Session session) {
        try {
            saveMdBoy(message, session, true);
        } catch (Exception e) {
            return ChainHandlerResult.empty().setResult(false).setMessage(e.getMessage()).setException(e);
        }
        return ChainHandlerResult.empty().setResult(true).setMessage("保存md文件内容成功!");
    }

    @Override
    public MessageTypeEnum getHandlerType() {
        return MessageTypeEnum.SAVE_MD_BODY;
    }

    @Override
    public boolean saveMdBoy(String message, Session session, boolean isSendMessage) {
        try {
            cache.put(session.getId(), message);
            //异步调用写入文件
            MessagePojo messagePojo = new MessagePojo();
            messagePojo.setMessageType(MessageTypeEnum.TISP_MSG.getMessageType());
            ThreadPool.getInstant().commit(() -> {
                File operationFile = null;
                try {
                    BlockingQueue<File> operationFileQueue = userInfoService.getOperationFile();
                    operationFile = operationFileQueue.peek();
                    //如果等于null
                    if (Objects.isNull(operationFile)) {
                        //则获取并移除
                        operationFile = operationFileQueue.take();
                        operationFileQueue.put(operationFile);
                    }
                } catch (InterruptedException e) {
                    // 超时等待
                    log.error("[SaveMdBodyHandlerMessageImpl]---[onMessage],获取数据被中断,异常信息为:{}", e);
                    throw new RuntimeException(e);
                }
                log.info("[SaveMdBodyHandlerMessageImpl]---[onMessage],当前获取到的操作文件为:{}", operationFile);
                if (Objects.isNull(operationFile)) {
                    messagePojo.setBody("当前操作文件为空");
                    sendMessage(messagePojo, isSendMessage);
                    throw new RuntimeException("当前操作文件为空!");
                }
                if (!operationFile.exists()) {
                    messagePojo.setBody("当前操作文件不存在");
                    sendMessage(messagePojo, isSendMessage);
                    throw new RuntimeException("当前操作文件不存在!");
                }

                try {
                    IoUtil.write(new FileOutputStream(operationFile), true, message.getBytes(StandardCharsets.UTF_8));
                    //写入成功之后，提示用户
                    messagePojo.setBody("保存成功!");
                    sendMessage(messagePojo, isSendMessage);
                    userInfoService.setFileSaveState(true).getUserLatelyInfo().setLatelyOperationFile(operationFile.getPath()).addHistoryOperation(operationFile.getPath());
                    modifyWindow.changeTitle();
                } catch (FileNotFoundException e) {
                    //写入失败提示用户
                    messagePojo.setBody("保存失败文件未找到,或已经被删除!");
                    sendMessage(messagePojo, isSendMessage);
                    throw new RuntimeException(e);
                }
                remotePullMdService.pushMdBody(message);
            });
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return true;
    }

    private void sendMessage(MessagePojo messagePojo, boolean isSend) {
        if (isSend) {
            webSocketSendMessage.sendMessage(messagePojo);
        }
    }
}
